package com.nulldev.util.web.flexibleKit.scfk.httpclient;

import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.nio.channels.WritableByteChannel;
import java.util.List;
import java.util.Map;

import com.nulldev.util.io.extensions.copyable.Copyable;
import com.nulldev.util.io.extensions.copyable.nio.NIOCopyable;
import com.nulldev.util.web.HttpClient.HttpResponse;
import com.nulldev.util.web.HttpClient.ResponseFormat;
import com.nulldev.util.web.HttpClient.Version;
import com.nulldev.util.web.flexibleKit.scfk.SCFKResponse;

public class SCFKClientResponse<T> implements HttpResponse<T>, Copyable, NIOCopyable {

	private final ResponseFormat format;
	private final SCFKResponse rsp;

	public SCFKClientResponse(final ResponseFormat format, final SCFKResponse r) {
		this.format = format;
		this.rsp = r;
	}

	@Override
	public void close() throws Exception {
		if (this.rsp.isKeepAlive()) {
			this.rsp.adaptiveClose();
		} else
			this.rsp.close();
	}

	@Override
	public void writeTo(final OutputStream os) throws IOException {
		this.rsp.writeTo(os);
	}

	@Override
	public int status() {
		return this.rsp.getResponseCode();
	}

	@Override
	public boolean successful() {
		return this.rsp.isSuccessful();
	}

	@Override
	public ResponseFormat format() {
		return this.format;
	}

	@SuppressWarnings("unchecked")
	@Override
	public T data() {
		try {
			if (this.format == ResponseFormat.STREAM) {
				return (T) this.rsp.asStream();
			} else if (this.format == ResponseFormat.READER) {
				return (T) new InputStreamReader(this.rsp.asStream());
			} else if (this.format == ResponseFormat.BYTES) {
				return (T) this.rsp.asByteArray();
			} else {
				return (T) this.rsp.asString();
			}
		} catch (IOException ex) {
			throw new RuntimeException(ex);
		}
	}

	@Override
	public T data(final boolean avoidDecoding) {
		return this.data();
	}

	@Override
	public T dataThenClose() {
		return this.dataThenClose(false);
	}

	@Override
	public T dataThenClose(final boolean avoidDecoding) {
		final T data = this.data();
		try {
			this.adaptiveClose();
		} catch (Exception e) {
		}
		return data;
	}

	@Override
	public Map<String, List<String>> headers() {
		return this.rsp.getHeaders();
	}

	@Override
	public String[] cookies() {
		final List<String> o = this.rsp.getHeaders().get("Set-Cookie");
		return o.toArray(new String[o.size()]);
	}

	@Override
	public void adaptiveClose() throws Exception {
		this.rsp.adaptiveClose();
	}

	@Override
	public Version transportVersion() {
		switch (this.rsp.getProtocol()) {
			case HTTP_0_9:
				return Version.HTTP_0_9;
			case HTTP_1_0:
				return Version.HTTP_1_0;
			case HTTP_1_1:
				return Version.HTTP_1_1;
			case HTTP_2_0:
				return Version.HTTP_2_0;
			case HTTP_3_0:
				return Version.HTTP_3_0;
			default:
				return HttpResponse.super.transportVersion();
		}
	}

	@Override
	public void writeTo(final WritableByteChannel os) throws IOException {
		this.rsp.writeTo(os);
	}

	@Override
	public void writeTo(final OutputStream os, final int preferredBufferSize) throws IOException {
		this.rsp.writeTo(os, preferredBufferSize);
	}

}
